import streamlit as st
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
from datetime import datetime

class MemoryMonitorView:
    """内存监控视图类"""
    
    def __init__(self, memory_monitor):
        self.memory_monitor = memory_monitor
    
    def render(self):
        """渲染内存监控页面"""
        st.markdown("<h1 class='main-header'>📊 内存监控报告</h1>", unsafe_allow_html=True)
        
        if not self.memory_monitor:
            st.error("内存监控未启用")
            return
        
        # 直接从memory_monitor获取监控报告
        report = self.memory_monitor.get_memory_report()
        
        if 'error' in report:
            st.error(report['error'])
            return
        
        # 基础信息
        col1, col2, col3, col4 = st.columns(4)
        
        # 修正第30-40行的代码
        with col1:
        # 检查current_snapshot是否存在
            if report.get('current_snapshot') and report['current_snapshot'].get('system'):
                current_system = report['current_snapshot']['system']
                st.metric(
                    "当前内存使用", 
                    f"{current_system['process_rss_mb']:.1f} MB",
                    f"{current_system['process_memory_percent']:.1f}%"
                )
            else:
                st.metric(
                    "当前内存使用", 
                    "未监控",
                    "0.0%"
                )
        
        with col2:
            # 计算监控时长
            if report.get('current_snapshot') and report['current_snapshot'].get('timestamp'):
                try:
                    snapshot_time = datetime.fromisoformat(report['current_snapshot']['timestamp'])
                    # 简单估算：假设第一个快照就是开始时间
                    duration_minutes = 30  # 默认显示30分钟，实际应该从监控开始时间计算
                    st.metric(
                        "监控时长", 
                        f"{duration_minutes:.1f} 分钟"
                    )
                except:
                    st.metric(
                        "监控时长", 
                        "未知"
                    )
            else:
                st.metric(
                    "监控时长", 
                    "未监控"
                )
        
        with col3:
            st.metric(
                "内存警告次数", 
                report.get('total_warnings', 0)
            )
        
        with col4:
            # 从current_snapshot中获取线程信息
            if (report.get('current_snapshot') and 
                report['current_snapshot'].get('threads') and 
                report['current_snapshot']['threads'].get('thread_count')):
                thread_count = report['current_snapshot']['threads']['thread_count']
            else:
                thread_count = 0
            
            st.metric(
                "活跃线程数", 
                thread_count
            )
        
        # 内存使用趋势图
        self._render_memory_trend(report)
        
        # 函数内存分析
        self._render_function_analysis(report)
        
        # 变量内存分析
        self._render_variable_analysis(report)
        
        # 内存分配热点
        self._render_memory_hotspots(report)
        
        # 操作按钮
        self._render_action_buttons()
    
    def _render_memory_trend(self, report):
        """渲染内存使用趋势图"""
        st.subheader("📈 内存使用趋势")
        
        if 'memory_history' in report and report['memory_history']:
            # 创建内存使用趋势图
            memory_data = []
            for entry in report['memory_history']:
                memory_data.append({
                    'timestamp': entry['timestamp'],
                    'rss_mb': entry['rss_mb'],
                    'percent': entry['percent']
                })
            
            df = pd.DataFrame(memory_data)
            df['timestamp'] = pd.to_datetime(df['timestamp'])
            
            fig = go.Figure()
            fig.add_trace(go.Scatter(
                x=df['timestamp'],
                y=df['rss_mb'],
                mode='lines+markers',
                name='内存使用 (MB)',
                line=dict(color='#1f77b4')
            ))
            
            fig.update_layout(
                title="内存使用趋势",
                xaxis_title="时间",
                yaxis_title="内存使用 (MB)",
                height=400
            )
            
            st.plotly_chart(fig, use_container_width=True)
        else:
            st.info("暂无内存趋势数据")
    
    def _render_function_analysis(self, report):
        """渲染函数内存分析"""
        st.subheader("🔍 函数内存分析")
        
        if 'function_memory' in report and report['function_memory']:
            # 创建函数内存使用表格
            func_data = []
            for func_name, memory_info in report['function_memory'].items():
                func_data.append({
                    '函数名': func_name,
                    '峰值内存 (MB)': f"{memory_info.get('peak_memory', 0):.2f}",
                    '平均内存 (MB)': f"{memory_info.get('avg_memory', 0):.2f}",
                    '调用次数': memory_info.get('call_count', 0),
                    '总耗时 (秒)': f"{memory_info.get('total_time', 0):.3f}"
                })
            
            df_func = pd.DataFrame(func_data)
            st.dataframe(df_func, use_container_width=True)
            
            # 函数内存使用柱状图
            if len(func_data) > 0:
                fig = px.bar(
                    df_func, 
                    x='函数名', 
                    y='峰值内存 (MB)',
                    title="函数峰值内存使用"
                )
                fig.update_layout(height=400)
                st.plotly_chart(fig, use_container_width=True)
        else:
            st.info("暂无函数内存分析数据")
    
    def _render_variable_analysis(self, report):
        """渲染变量内存分析"""
        st.subheader("📊 变量内存分析")
        
        if 'variable_memory' in report and report['variable_memory']:
            # 创建变量内存使用表格
            var_data = []
            for var_name, memory_info in report['variable_memory'].items():
                var_data.append({
                    '变量名': var_name,
                    '内存大小 (MB)': f"{memory_info.get('size_mb', 0):.2f}",
                    '类型': memory_info.get('type', 'Unknown'),
                    '位置': memory_info.get('location', 'Unknown')
                })
            
            df_var = pd.DataFrame(var_data)
            st.dataframe(df_var, use_container_width=True)
            
            # 变量内存占用饼图
            if len(var_data) > 0:
                fig = px.pie(
                    df_var, 
                    values='内存大小 (MB)', 
                    names='变量名',
                    title="变量内存占用分布"
                )
                fig.update_layout(height=400)
                st.plotly_chart(fig, use_container_width=True)
        else:
            st.info("暂无变量内存分析数据")
    
    def _render_memory_hotspots(self, report):
        """渲染内存分配热点"""
        st.subheader("🔥 内存分配热点 (tracemalloc)")
        
        if 'tracemalloc_top' in report and report['tracemalloc_top']:
            # 创建热点分析表格
            hotspot_data = []
            for i, trace in enumerate(report['tracemalloc_top'][:10]):  # 显示前10个热点
                hotspot_data.append({
                    '排名': i + 1,
                    '文件': trace.get('filename', 'Unknown'),
                    '行号': trace.get('lineno', 'Unknown'),
                    '内存大小 (MB)': f"{trace.get('size_mb', 0):.2f}",
                    '占比 (%)': f"{trace.get('percent', 0):.1f}"
                })
            
            df_hotspot = pd.DataFrame(hotspot_data)
            st.dataframe(df_hotspot, use_container_width=True)
            
            # 热点内存分布图
            if len(hotspot_data) > 0:
                fig = px.bar(
                    df_hotspot, 
                    x='排名', 
                    y='内存大小 (MB)',
                    hover_data=['文件', '行号'],
                    title="内存分配热点分布"
                )
                fig.update_layout(height=400)
                st.plotly_chart(fig, use_container_width=True)
        else:
            st.info("暂无内存热点数据")
        
        # 显示内存峰值记录
        if 'memory_peaks' in report and report['memory_peaks']:
            st.subheader("⚠️ 内存峰值记录")
            peak_data = []
            for peak in report['memory_peaks'][-5:]:  # 显示最近5次峰值
                peak_data.append({
                    '时间': peak.get('timestamp', 'Unknown'),
                    '内存使用 (MB)': f"{peak.get('memory_mb', 0):.1f}",
                    '触发函数': peak.get('function', 'Unknown'),
                    '描述': peak.get('description', '')
                })
            
            df_peaks = pd.DataFrame(peak_data)
            st.dataframe(df_peaks, use_container_width=True)
    
    def _render_action_buttons(self):
        """渲染操作按钮"""
        st.divider()
        col1, col2, col3 = st.columns(3)
        
        with col1:
            if st.button("🔄 刷新数据", use_container_width=True):
                st.rerun()
        
        with col2:
            if st.button("📊 生成报告", use_container_width=True):
                try:
                    report_path = self.memory_monitor.export_memory_report()
                    if report_path:
                        st.success(f"报告已导出到: {report_path}")
                    else:
                        st.error("报告导出失败")
                except Exception as e:
                    st.error(f"报告导出失败: {str(e)}")
        
        with col3:
            if st.button("🗑️ 清空历史", use_container_width=True):
                try:
                    if hasattr(self.memory_monitor, 'clear_history'):
                        self.memory_monitor.clear_history()
                        st.success("历史数据已清空")
                    else:
                        st.info("该功能暂未实现")
                except Exception as e:
                    st.error(f"清空历史失败: {str(e)}")